---
id: user-login-user-registration
title: User Login And Registration
sidebar_label: Overview
---

import Mermaid from '@theme/Mermaid'

ORY Kratos supports two type of login and registration flows:

- Browser-based (easy): This flow works for all applications running on top of a
  browser. Websites, single-page apps, Cordova/Ionic, and so on.
- API-based (advanced): This flow works for native applications like iOS
  (Swift), Android (Java), Microsoft (.NET), React Native, Electron, and others.

The login and registration flows documented here are the foundation for the
[password](user-login-user-registration/username-email-password.mdx) and
[social](user-login-user-registration/openid-connect-social-sign-in-oauth2.mdx)
sign in and sign up strategies.

## Self-Service User Login and User Registration for Browser Applications

ORY Kratos supports browser applications that run on server-side (e.g. Java,
NodeJS, PHP) as well as client-side (e.g. JQuery, ReactJS, AngularJS, ...).

Browser-based login and registration makes use of three core HTTP technologies:

- HTTP Redirects
- HTTP POST (`application/json`, `application/x-www-urlencoded`) and RESTful GET
  requests.
- HTTP Cookies to prevent CSRF and Session Hijaking attack vectors.

The browser flow is the easiest and most secure to set up and integrated with.
ORY Kratos takes care of all required session and CSRF cookies and ensures that
all security requirements are fulfilled.

Future versions of ORY Kratos will be able to deal with multi-domain
environments that require SSO. For example, one account would be used to sign
into both `mydomain.com` and `anotherdomain.org`. A common real-world example is
using your Google account to seamlessly be signed into YouTube and Google at the
same time.

This flow is not suitable for scenarios where you use purely programmatic
clients that do not work well with HTTP Cookies and HTTP Redirects.

### The Login and Registration User Interface

The Login and Registration User Interface is a route (page / site) in your
application that should render a sign in and registration form:

```html
<!-- Login -->
<form action="..." method="POST">
  <input type="text" name="identifier" placeholder="Enter your username" />
  <input type="password" name="password" placeholder="Enter your password" />
  <input type="hidden" name="csrf_token" value="cdef..." />
  <input type="submit" />
</form>

<!-- Registration -->
<form action="..." method="POST">
  <input type="email" name="email" placeholder="Enter your E-Mail Address" />
  <input type="password" name="password" placeholder="Enter your password" />
  <input
    type="first_name"
    name="password"
    placeholder="Enter your First Name"
  />
  <input type="last_name" name="password" placeholder="Enter your Last Name" />
  <input type="hidden" name="csrf_token" value="cdef..." />
  <input type="submit" />
</form>
```

Once implemented (using e.g. our
[reference implementation](https://github.com/ory/kratos-selfservice-ui-node))
you reference these routes in your ORY Kratos config file:

```yaml title="path/to/kratos/config.yml"
urls:
  login_ui: https://.../login
  registration_ui: https://.../registration
```

Depending on the type of login flows you want to support, you may a also add a
"Sign up/in with GitHub" flow:

```html
<!-- Login and Registration -->
<form action="..." method="POST">
  <input type="hidden" name="csrf_token" value="cdef..." />

  <!-- Basically <a href="https://github.com/login/oauth/authorize?...">Sign up/in with GitHub</a> -->
  <input type="submit" name="provider" value="GitHub" />
</form>
```

In stark contrast to other Identity Systems, ORY Kratos does not render this
HTML. Instead, you need to implement the HTML code in your application (e.g.
NodeJS + ExpressJS, Java, PHP, ReactJS, ...), which gives you extreme
flexibility and customizability in your user interface flows and designs.

Each Login and Registration Strategy (e.g.
[Username and Password](user-login-user-registration/username-email-password.mdx),
[Social Sign In](user-login-user-registration/openid-connect-social-sign-in-oauth2.mdx),
Passwordless, ...) works a bit different but they all boil down to the same
abstract sequence:

<Mermaid
  chart={`
sequenceDiagram
  participant B as Browser
  participant K as ORY Kratos
  participant A as Your Application
  B->>K: Initiate Login
  K->>B: Redirects to your Application's /login endpoint
  B->>A: Calls /login
  A-->>K: Fetches data to render forms etc
  B-->>A: Fills out forms, clicks e.g. "Submit Login"
  B->>K: POSTs data to
  K-->>K: Processes Login Info
  alt Login data valid
    K-->>B: Sets session cookie
    K->>B: Redirects to e.g. Dashboard
  else Login data invalid
    K-->>B: Redirects to your Applicaiton's /login endpoint
    B->>A: Calls /login
    A-->>K: Fetches data to render form fields and errors
    B-->>A: Fills out forms again, corrects errors
    B->>K: POSTs data again - and so on...
  end
`}
></Mermaid>

The exact data being fetched and the step _"Processes Login / Registration
Info"_ depend, of course, on the actual Strategy being used. But it is important
to understand that **"Your Application"** is responsible for rendering the
actual Login and Registration HTML Forms. You can of course implement one app
for rendering all the Login, Registration, ... screens, and another app (think
"Service Oriented Architecture", "Micro-Services" or "Service Mesh") is
responsible for rendering your Dashboards, Management Screens, and so on.

:::note

It is RECOMMENDED to put all applications (or "services"), including ORY Kratos,
behind a common API Gateway or Reverse Proxy. This greatly reduces the amount of
work you have to do to get all the Cookies working properly. We RECOMMEND using
[ORY Oathkeeper](http://github.com/ory/oathkeeper) for this as it integrates
best with the ORY Ecosystem and because all of our examples use ORY Oathkeeper.
You MAY of course use any other reverse proxy (Envoy, AWS API Gateway,
Ambassador, Nginx, Kong, ...), but we do not have examples or guides for those
at this time.

:::

### Code

Because Login and Registration are so similar, we can use one common piece of
code to cover both. A functioning example of the code and approach used here can
be found on
[github.com/ory/kratos-selfservice-ui-node](https://github.com/ory/kratos-selfservice-ui-node).

The code example used here is universal and does not use an SDK because we want
you to understand the fundamentals of how this flow works.

#### Server-side route

While this example assumes a Server-Side Application, a Client-Side (e.g.
ReactJS) Application would work the same, but use ORY Kratos' Public API
instead.

```js
// Uses the ORY Kratos NodeJS SDK - for more SDKs check:
//
//  https://www.ory.sh/kratos/docs/sdk/index
const { AdminApi } = require('@oryd/kratos-client')

// The browser config key is used to redirect the user. It reflects where ORY Kratos' Public API
// is accessible from. Here, we're assuming traffic going to `http://example.org/.ory/kratos/public/`
// will be forwarded to ORY Kratos' Public API.
const kratosBrowserUrl = 'http://example.org/.ory/kratos/public/'

// Initializes the SDK with ORY Kratos' Admin API.
const adminEndpoint = new AdminApi('https://ory-kratos-admin.example-org.vpc/')

// The parameter "flow" can be "login" and "registration".
// You would register the two routes in express js like this:
//
//  app.get('/auth/registration', authHandler('registration'))
//  app.get('/auth/login', authHandler('login'))
//
export const authHandler = (flow) => (req, res, next) => {
  // The request ID is used to identify the login and registraion request and
  // return data like the csrf_token and so on.
  const request = req.query.request
  if (!request) {
    console.log(`No request found in URL, initializing ${flow} flow.`)
    res.redirect(`${kratosBrowserUrl}/self-service/browser/${flow}`)
    return
  }

  const authRequest =
    type === 'login'
      ? adminEndpoint.getSelfServiceBrowserLoginRequest(request)
      : adminEndpoint.getSelfServiceBrowserRegistrationRequest(request)

  authRequest.then(({ body, response }) => {
    if (response.statusCode !== 200) {
      res.redirect(
        `${config.kratos.browser}/self-service/browser/flows/${type}`
      )
      return
    }

    // "body" contains all the request data for this Registration request.
    // You can process that data here, if you want.

    // only show the form section that is "active" to avoid user confusion.
    let password = body.methods.password.config
    let oidc = body.methods.oidc.config
    switch (body.active) {
      case 'password':
        oidc = undefined // if password is active hide this
        break
      case 'oidc':
        password = undefined // if oidc is active hide this
        break
    }

    // Lastly, you probably want to render the data using a view (e.g. Jade Template):
    res.render(flow, { oidc, password })
  })
  // Handle errors using ExpressJS' next functionality:
  //
  //    .catch(next)
}
```

#### Views

Your views can be rather simple, as ORY Kratos provides you with all the
information you need for rendering the forms. The following example illustrates
a generic form generator (we use handlebars here) that works with ORY Kratos:

```handlebars name="views/partials/form.hbs"
{{~#each messages~}}
    <!-- global messages for this flow -->
    <div class="message {{type}}">{{text}}</div>
{{~/each~}}

<form action="{{form.action}}" method="{{form.method}}">
    {{~#each form.messages~}}
        <!-- messages for this form -->
        <div class="message {{type}}">{{text}}</div>
    {{~/each~}}

    {{#each form.fields}}
        {{~#each messages~}}
            <!-- messages for individual fields -->
            <div class="message {{type}}">{{text}}</div>
        {{~/each~}}

        <input name="{{name}}" type="{{type}}" value="{{value}}" {{#if disabled}}disabled{{/if}}>
    {{/each}}

    <button type="submit">Register</button>

    <!--
        This example also works for the login screen:

            <button type="submit">Sign in</button>
    -->
</form>
```

In your main "Login" or "Sign Up" view you would then consume this template for
all the methods you want to support:

```handlebars name="views/login_or_signup.hbs"
<!-- Username / Email and Password login / sign up form: -->
{{#if password}}
    {{> form form=password}}
{{/if}}

<!-- Social sign in/up form: -->
{{#if oidc}}
    {{> form form=oidc}}
{{/if}}

<!-- ... form: -->
<!-- ... -->
```

For details on payloads and potential HTML snippets consult the individual
Self-Service Strategies for:

- [Username and Password Strategy](user-login-user-registration/username-email-password.mdx)
- [Social Sign In Strategy](user-login-user-registration/openid-connect-social-sign-in-oauth2.mdx)

### Server-Side Browser Applications

Let's take a look at the concrete network topologies, calls, and payloads. Here,
we're assuming that you're running a server-side browser application (written in
e.g. PHP, Java, NodeJS) to render the login and registration screen on the
server and make all API calls from that server code. The counterpart to this
would be a client-side browser application (written in e.g. Vanilla JavaScript,
JQuery, ReactJS, AngularJS, ...) that uses AJAX requests to fetch data. For
these type of applications, read this section first and go to section
[Client-Side Browser Applications](#client-side-browser-applications) next.

#### Network Architecture

We recommend checking out the
[Quickstart Network Architecture](../../quickstart.mdx#network-architecture) for
a high-level, exemplary, overview of the network. In summary:

1. The SecureApp (your application) is exposed at http://127.0.0.1:4455 and
   proxies requests matching path `./ory/kratos/public/*` to ORY Krato's Public
   API Port.
1. ORY Kratos exposes (for debugging only!!) the Public API at
   http://127.0.0.1:4433 and Admin API at http://127.0.0.1:4434.
1. Within the "intranet" or "private network", ORY Kratos is exposed at
   http://kratos:4433 and http://kratos:4434. These URLs are be used by the
   SecureApp to communicate with ORY Kratos.

Keep in mind that his architecture is just one of many possible network
architectures. It is however one of the simplest as well and it works locally.
For production deployments you would probably use an Reverse Proxy such as
Nginx, Kong, Envoy, ORY Oathkeeper, or others.

#### User Login and User Registration Process Sequence

The Login and Registration User Flow is composed of several high-level steps
summarized in this state diagram:

<Mermaid
  chart={`
stateDiagram
  s1: User browses app
  s2: Execute "Before Login/Registration Hook(s)"
  s3: User Interface Application renders "Login/Registration Request"
  s4: Execute "After Login/Registration Hook(s)"
  s5: Update "Login/Registration Request" with Error Context(s)
  s6: Login/Registration successful
	[*] --> s1
  s1 --> s2 : User clicks "Log in / Sign up"
  s2 --> Error : A hook fails
  s2 --> s3 : User is redirected to Login/Registration UI URL
  s3 --> s4 : User provides valid credentials/registration data
  s3 --> s5 : User provides invalid credentials/registration data
  s5 --> s3 : User is redirected to Login/Registration UI URL
  s4 --> Error : A Hook fails
  s4 --> s6
  s6 --> [*]
  Error --> [*]
`}
></Mermaid>

1. The **Login/Registration User Flow** is initiated because a link was clicked
   or an action was performed that requires an active user session.
1. ORY Kratos executes Jobs defined in the **Before Login/Registration
   Workflow**. If a failure occurs, the whole flow is aborted.
1. The user's browser is redirected to
   `http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/(login|registration)`
   (the notation `(login|registration)` expresses the two possibilities of
   `../self-service/browser/flows/login` or
   `../self-service/browser/flows/registration`).
1. ORY Kratos does some internal processing (e.g. checks if a session cookie is
   set, generates payloads for form fields, sets CSRF token, ...) and redirects
   the user's browser to the Login UI URL which is defined using the
   `urls.login_ui` (or `urls.registration_ui`) config or `URLS_LOGIN_UI` (or
   `URLS_REGISTRATION_UI`) environment variable, which is set to the ui
   endpoints - for example `https://127.0.0.1:4455/auth/login` and
   `https://127.0.0.1:4455/auth/registration`). The user's browser is thus
   redirected to
   `https://127.0.0.1:4455/auth/(login|registration)?request=abcde`. The
   `request` query parameter includes a unique ID which will be used to fetch
   contextual data for this login request.
1. Your Server-Side Application makes a `GET` request to
   `http://kratos:4434/self-service/browser/flows/requests/(login|registration)?request=abcde`.
   ORY Kratos responds with a JSON Payload that contains data (form fields,
   error messages, ...) for all enabled User Login Strategies:
   ```json5
   {
     id: 'abcde',
     methods: {
       password: { method: 'password', config: { action: '...', fields: [] } },
       oidc: { method: 'oidc', config: { action: '...', fields: [] } }
     }
   }
   ```
1. Your Server-Side applications renders the data however you see fit. The User
   interacts with it an completes the Login by clicking, for example, the
   "Login", the "Login with Google", ... button.
1. The User's browser makes a request to one of ORY Kratos' Strategy URLs (e.g.
   `http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/strategies/password/(login|registration)`
   or
   `https://127.0.0.1:4455/.ory/kratos/public/self-service/browser/strategies/oidc/auth/abcde`).
   ORY Kratos validates the User's credentials (when logging in - e.g. Username
   and Password, by performing an OpenID Connect flow, ...) or the registration
   form data (when signing up - e.g. is the E-Mail address valid, is the person
   at least 21 years old, ...):
   - If the credentials / form data is invalid, the Login Request's JSON Payload
     is updated - for example with
     ```json5
     {
       id: 'abcde',
       methods: {
         oidc: {
           method: 'oidc',
           config: {
             /* ... */
           }
         },
         password: {
           method: 'password',
           config: {
             /* ... */
             messages: [
               {
                 id: 4000006,
                 text: 'The provided credentials are invalid. Check for spelling mistakes in your password or username, email address, or phone number.',
                 type: 'error'
               }
             ]
           }
         }
       }
     }
     ```
     and the user's Browser is redirected back to the Login UI:
     `https://127.0.0.1:4455/auth/(login|registration)?request=abcde`.
   - If credentials / data is valid, ORY Kratos proceeds with the next step.
   - If the flow is a registration request and the registration data is valid,
     the identity is created.
1. ORY Kratos executes hooks defined in the **After Login/Registration Hooks**.
   If a failure occurs, the whole flow is aborted.
1. The client receives the expected response. For browsers, this is a HTTP
   Redirection, for API clients it will be a JSON response containing the
   session and/or identity. For more information on this topic check
   [Self-Service Flow Completion](../../concepts/browser-redirect-flow-completion.mdx).

<Mermaid
  chart={`
sequenceDiagram
  participant B as Browser
  participant A as Your Server-Side Application
  participant KP as ORY Kratos Public API
  participant KA as ORY Kratos Admin API
  B->>+A: GET /.ory/kratos/public/self-service/browser/flows/(login|registration)
  A->>+KP: GET /self-service/browser/flows/login(login|registration)
  KP-->>KP: Execute Hooks defined in "Before Login/Registration"
  KP-->>-A: HTTP 302 Found /auth/(login|registration)?request=abcde
  A-->>-B: HTTP 302 Found /auth/(login|registration)?request=abcde
  B->>+A: GET /auth/(login|registration)?request=abcde
  A->>+KA: GET/self-service/browser/flows/requests/(login|registration)?request=abcde
  KA->>-A: Sends Login/Registration Request JSON Payload
  Note over A,KA:  {"methods":{"password":...,"oidc":..}}
  A-->>A: Generate and render HTML
  A-->>-B: Return HTML (Form, ...)
  B-->>B: Fill out HTML
  B->>+KP: POST HTML Form
  KP-->>KP: Checks login / registration data
  alt Login data is valid
    KP-->>-KP: Execute Jobs defined in "After Login Workflow(s)"
    KP-->>A: HTTP 302 Found /dashboard
    Note over KP,B: Set-Cookie: auth_session=...
    B->>+A: GET /dashboard
    A-->KA: Validates Session Cookie
    A->>-B: Send Dashboard Response
  else Login data is invalid
    Note over KP,B: User retries login / registration
    KP-->>B: HTTP 302 Found /auth/(login|registration)?request=abcde
  end
`}
></Mermaid>

### Client-Side Browser Applications

Because Client-Side Browser Applications do not have access to ORY Kratos' Admin
API, they must use the ORY Kratos Public API instead. The flow for a Client-Side
Browser Application is almost the exact same as the one for Server-Side
Applications, with the small difference that
`https://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/requests/login?request=abcde`
would be called via AJAX instead of making a request to
`https://kratos:4434/self-service/browser/flows/requests/login?request=abcde`.

To prevent brute force, guessing, session injection, and other attacks, it is
required that cookies are working for this endpoint. The cookie set in the
initial HTTP request made to
`https://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/login`
MUST be set and available when calling this endpoint!

:::info

The initialization request
(`http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/(login|registration)`)
**cannot** be made via AJAX or API requests. You **must** open that URL in the
user's browser using e.g. `window.open` `location.href` or plain and simple old
`<a href=...>`.

:::

## Self-Service User Login and User Registration for API Clients

Will be addressed in a future release.

## Hooks

ORY Kratos allows you to configure hooks that run before and after a Login or
Registration Request is generated. This may be helpful if you'd like to restrict
logins to IPs coming from your internal network or other logic.

For more information about hooks please read the
[Hook Documentation](../hooks/index.mdx).

## Refreshing a Session

In some cases it is required to refresh a login session. This is the case when
updating one's password. Refreshing a session updates the `authenticated_at`
time.

:::info

Refreshing a session will not log the user out, unless another user signs in.

:::

To refresh a session, append `?refresh=true` to
`/self-service/browser/flows/login`, for example
`http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/login?refresh=true`.
